﻿using ServerListerner.Enums;
using ServerListerner.Model;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.Json;

namespace ServerListerner.Helper
{
    public static class HTTPHelper
    {
    //    public static HTTPRequest HTTPDecoder(this string str)
    //    {
    //        HTTPRequest httpReq = new HTTPRequest();
    //        string[] Header_Body=str.Split(new string[] { "\r\n\r\n"},StringSplitOptions.None);
    //        if(Header_Body.Length==2)
    //            httpReq.Body = Header_Body[1];
    //        string Header = Header_Body[0];
    //        string[] headers = Header.Split(new string[] { "\r\n" }, StringSplitOptions.None);
    //        if (headers.Length > 0)
    //        {
    //            string[] head_first = headers[0].Split(' ');
    //            if (head_first.Length == 3)
    //            {
    //                httpReq.Method = head_first[0];
    //                string[] _url = head_first[1].Split("?");
    //                if(_url.Length>0)
    //                    httpReq.Url = _url[0];
    //                if (_url.Length > 1)
    //                    httpReq.Params = _url[1].GetParams();
    //                httpReq.Version= head_first[2];
    //            }
    //            Dictionary<string,string> header = new Dictionary<string, string>();
    //            for (int i = 1; i < headers.Length; i++) {
    //                string[]? head = headers[i].Split(new string[] { ": "},StringSplitOptions.None);
    //                if (head!=null&&head.Length==2)
    //                {
    //                    header.Add(head[0].ClearSpace(), head[1].ClearSpace());
    //                }
    //            }
    //            httpReq.Headers = header;
    //        }
    //        return httpReq;
    //    }

        public static HTTPRequest HTTPDecoder(this byte[] _SocketData,int size,Encoding? encoding=null)
        {
            HTTPRequest httpReq = new HTTPRequest();
            if (_SocketData == null) return httpReq;
            using (MemoryStream ms = new MemoryStream(_SocketData))
            {
                using (StreamReader sr = new StreamReader(ms))
                {
                    bool isFirstRead = true;
                    Dictionary<string, string> header = new Dictionary<string, string>();
                    while (!sr.EndOfStream)
                    {
                        string _str = sr.ReadLine();
                        if (string.IsNullOrEmpty(_str))
                            break;
                        if (isFirstRead)
                        {
                            string[] head_first = _str.Split(' ');
                            if (head_first.Length == 3)
                            {
                                httpReq.Method = head_first[0];
                                string[] _url = head_first[1].Split("?");
                                if (_url.Length > 0)
                                    httpReq.Url = _url[0];
                                if (_url.Length > 1)
                                    httpReq.Params = _url[1].GetParams();
                                httpReq.Version = head_first[2];
                                isFirstRead = false;
                                continue;
                            }
                        }
                        string[]? head = _str.Split(new string[] { ": " }, StringSplitOptions.None);
                        if (head != null && head.Length == 2)
                            header.Add(head[0].ClearSpace(), head[1].ClearSpace());
                    }
                    httpReq.Headers = header;
                    var _obj = header.Where(s => s.Key.ToLower() == "Content-Length".ToLower()).FirstOrDefault().Value??"0";
                    int length = Convert.ToInt32(_obj);
                    byte[] BodyData = _SocketData.Skip(size - length).Take(length).ToArray();
                    httpReq.Body = BodyData;
                    httpReq.Content = (encoding??Encoding.UTF8).GetString(BodyData);
                }
                return httpReq;
            }
        }


        private static Dictionary<string, object> GetParams(this string str)
        {
            Dictionary<string, object> _params = new Dictionary<string, object>();
            if (string.IsNullOrEmpty(str))
                return _params;
            string[] param=str.Split('&');
            foreach (string s in param) {
                string[] keyValue = s.Split("=");
                if (keyValue.Length == 2) {
                    _params.Add(keyValue[0], keyValue[1]);
                }
            }
            return _params;
        }
        public static byte[] HTTPEncoder(this HTTPResponse resp, Encoding encoding = null)
        {
            resp.Version = resp.Version ?? HTTPVersion.V1_1.GetDescription();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.Append(string.Join(' ', new string[3] { resp.Version, ((int)resp.Code).ToString(), resp.Code.ToString() }));
            stringBuilder.Append("\r\n");
            resp.Body = string.IsNullOrEmpty(resp.Content) ? new byte[0] : encoding == null?Encoding.UTF8.GetBytes(resp.Content) :encoding.GetBytes(resp.Content);
            if (resp.Headers != null)
            {
                if (resp.Headers.ContainsKey("Content-Length"))
                    resp.Headers["Content-Length"] = resp.Body.Length.ToString();
            }
            else
            {
                resp.Headers = new Dictionary<string, string>();
                resp.Headers.Add("Content-Length", resp.Body.Length.ToString());
            }
            foreach (var item in resp.Headers)
            {
                stringBuilder.Append($@"{item.Key}:{item.Value}");
                stringBuilder.Append("\r\n");
            }
            stringBuilder.Append("\r\n");
            stringBuilder.Append(resp.Content);
            string _str_response=stringBuilder.ToString();
            encoding = encoding ?? Encoding.UTF8;
            byte[] resp_data = encoding.GetBytes(_str_response) ?? new byte[0];
            return resp_data;
        }

        public static Dictionary<string, string> AddHeader(this Dictionary<string, string> _source, Dictionary<string, string> _addHeader)
        {
            if (_addHeader != null)
                foreach (var item in _addHeader)
                {
                    if (!_source.Any(s => s.Key == item.Key))
                        _source.Add(item.Key, item.Value);
                }
            return _source;
        }
        public static Dictionary<string, string> RemoveHeaderHost(this Dictionary<string, string> _source)
        {
            List<string> removeHost = new List<string>();
            removeHost.Add("host");
            return _source.RemoveHeader(removeHost);
        }
        public static Dictionary<string, string> RemoveHeader(this Dictionary<string, string> _source, List<string> Key)
            =>_source.Where(s => !Key.Any(x => x.ToLower() == s.Key.ToLower()))
            .ToDictionary(s => s.Key, s => s.Value);

        public static string? ResultData(this object? obj)
        {
            if (obj == null) return string.Empty;
            Type type = obj.GetType();
            if (type ==typeof(string)) return obj.ToString();
            else
               return  System.Text.Json.JsonSerializer.Serialize(obj, new JsonSerializerOptions()
                {
                    Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
                });
        }
    }
    public class ListenPath
    {
        public string? Method { get; set; }
        public string? Path { get; set; }
    }
}
